use async_trait::async_trait;
use rustcloud_core::{
    LoadBalancer, ServiceInstance, ServiceResult, RequestContext, InstanceMetrics, StrategyInfo
};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::{HashMap, BTreeMap};
use std::sync::{Arc, RwLock};
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
use std::time::{Duration, SystemTime};
use tokio::sync::RwLock as AsyncRwLock;

/// 轮询负载均衡策略
pub struct RoundRobin {
    counter: AtomicUsize,
}

impl RoundRobin {
    pub fn new() -> Self {
        Self {
            counter: AtomicUsize::new(0),
        }
    }
}

#[async_trait]
impl LoadBalancer for RoundRobin {
    async fn select(
        &self,
        _service_name: &str,
        instances: &[ServiceInstance],
    ) -> ServiceResult<Option<ServiceInstance>> {
        if instances.is_empty() {
            return Ok(None);
        }
        
        // 过滤健康的实例
        let healthy_instances: Vec<&ServiceInstance> = instances
            .iter()
            .filter(|instance| instance.healthy)
            .collect();
        
        if healthy_instances.is_empty() {
            return Ok(None);
        }
        
        let index = self.counter.fetch_add(1, Ordering::Relaxed) % healthy_instances.len();
        Ok(healthy_instances.get(index).map(|&instance| instance.clone()))
    }

    fn name(&self) -> &str {
        "round_robin"
    }
    
    fn get_strategy_info(&self) -> StrategyInfo {
        StrategyInfo {
            name: "Round Robin".to_string(),
            description: "轮询负载均衡算法，按顺序选择服务实例".to_string(),
            requires_session_affinity: false,
            supports_weighted_routing: false,
        }
    }
}

/// 随机负载均衡策略
pub struct Random {
    // 随机策略不需要状态
}

impl Random {
    pub fn new() -> Self {
        Self {}
    }
}

#[async_trait]
impl LoadBalancer for Random {
    async fn select(
        &self,
        _service_name: &str,
        instances: &[ServiceInstance],
    ) -> ServiceResult<Option<ServiceInstance>> {
        if instances.is_empty() {
            return Ok(None);
        }
        
        // 过滤健康的实例
        let healthy_instances: Vec<&ServiceInstance> = instances
            .iter()
            .filter(|instance| instance.healthy)
            .collect();
        
        if healthy_instances.is_empty() {
            return Ok(None);
        }
        
        let index = rand::random::<usize>() % healthy_instances.len();
        Ok(healthy_instances.get(index).map(|&instance| instance.clone()))
    }

    fn name(&self) -> &str {
        "random"
    }
    
    fn get_strategy_info(&self) -> StrategyInfo {
        StrategyInfo {
            name: "Random".to_string(),
            description: "随机负载均衡算法，随机选择健康的服务实例".to_string(),
            requires_session_affinity: false,
            supports_weighted_routing: false,
        }
    }
}

/// 加权轮询负载均衡策略
pub struct WeightedRoundRobin {
    weights: Arc<RwLock<HashMap<String, usize>>>,
}

impl WeightedRoundRobin {
    pub fn new() -> Self {
        Self {
            weights: Arc::new(RwLock::new(HashMap::new())),
        }
    }
}

#[async_trait]
impl LoadBalancer for WeightedRoundRobin {
    async fn select(
        &self,
        _service_name: &str,
        instances: &[ServiceInstance],
    ) -> ServiceResult<Option<ServiceInstance>> {
        if instances.is_empty() {
            return Ok(None);
        }
        
        // 过滤健康的实例
        let healthy_instances: Vec<&ServiceInstance> = instances
            .iter()
            .filter(|instance| instance.healthy)
            .collect();
        
        if healthy_instances.is_empty() {
            return Ok(None);
        }
        
        // 计算总权重
        let total_weight: f64 = healthy_instances
            .iter()
            .map(|instance| instance.weight)
            .sum();
        
        if total_weight <= 0.0 {
            // 如果没有权重，回退到普通轮询
            let index = rand::random::<usize>() % healthy_instances.len();
            return Ok(healthy_instances.get(index).map(|&instance| instance.clone()));
        }
        
        // 按照权重选择实例
        let mut random_weight = rand::random::<f64>() * total_weight;
        
        for instance in &healthy_instances {
            random_weight -= instance.weight;
            if random_weight <= 0.0 {
                return Ok(Some((*instance).clone()));
            }
        }
        
        // 如果上面没有选中，返回第一个
        Ok(healthy_instances.first().map(|&instance| instance.clone()))
    }

    fn name(&self) -> &str {
        "weighted_round_robin"
    }
    
    fn get_strategy_info(&self) -> StrategyInfo {
        StrategyInfo {
            name: "Weighted Round Robin".to_string(),
            description: "加权轮询负载均衡算法，按照实例权重进行加权选择".to_string(),
            requires_session_affinity: false,
            supports_weighted_routing: true,
        }
    }
}

/// 一致性哈希负载均衡策略
pub struct ConsistentHash {
    virtual_nodes: usize,
}

impl ConsistentHash {
    pub fn new() -> Self {
        Self {
            virtual_nodes: 160, // 默认虚拟节点数量
        }
    }
    
    pub fn with_virtual_nodes(virtual_nodes: usize) -> Self {
        Self { virtual_nodes }
    }
    
    /// 计算字符串的哈希值
    fn hash(&self, key: &str) -> u64 {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish()
    }
    
    /// 构建一致性哈希环
    fn build_hash_ring<'b>(&self, instances: &[&'b ServiceInstance]) -> BTreeMap<u64, &'b ServiceInstance> {
        let mut ring = BTreeMap::new();
        
        for instance in instances {
            for i in 0..self.virtual_nodes {
                let virtual_key = format!("{}:{}", instance.address(), i);
                let hash_value = self.hash(&virtual_key);
                ring.insert(hash_value, *instance);
            }
        }
        
        ring
    }
    
    /// 根据键找到对应的实例
    fn find_instance<'b>(&self, key: &str, ring: &BTreeMap<u64, &'b ServiceInstance>) -> Option<&'b ServiceInstance> {
        if ring.is_empty() {
            return None;
        }
        
        let hash = self.hash(key);
        
        // 找到第一个大于等于哈希值的节点
        if let Some((_, instance)) = ring.range(hash..).next() {
            Some(instance)
        } else {
            // 如果没有找到，返回环上的第一个节点
            ring.values().next().copied()
        }
    }
}

#[async_trait]
impl LoadBalancer for ConsistentHash {
    async fn select(
        &self,
        service_name: &str,
        instances: &[ServiceInstance],
    ) -> ServiceResult<Option<ServiceInstance>> {
        if instances.is_empty() {
            return Ok(None);
        }
        
        // 过滤健康的实例
        let healthy_instances: Vec<&ServiceInstance> = instances
            .iter()
            .filter(|instance| instance.healthy)
            .collect();
        
        if healthy_instances.is_empty() {
            return Ok(None);
        }
        
        // 构建哈希环
        let ring = self.build_hash_ring(&healthy_instances);
        
        // 使用服务名作为哈希键
        let instance = self.find_instance(service_name, &ring);
        
        Ok(instance.map(|inst| inst.clone()))
    }

    fn name(&self) -> &str {
        "consistent_hash"
    }
    
    fn get_strategy_info(&self) -> StrategyInfo {
        StrategyInfo {
            name: "Consistent Hash".to_string(),
            description: "一致性哈希负载均衡算法，保证相同请求总是路由到同一实例".to_string(),
            requires_session_affinity: true,
            supports_weighted_routing: false,
        }
    }
    
    async fn select_with_context(
        &self,
        service_name: &str,
        instances: &[ServiceInstance],
        context: &RequestContext,
    ) -> ServiceResult<Option<ServiceInstance>> {
        if instances.is_empty() {
            return Ok(None);
        }
        
        // 过滤健康的实例
        let healthy_instances: Vec<&ServiceInstance> = instances
            .iter()
            .filter(|instance| instance.healthy)
            .collect();
        
        if healthy_instances.is_empty() {
            return Ok(None);
        }
        
        // 构建哈希环
        let ring = self.build_hash_ring(&healthy_instances);
        
        // 优先使用session_id作为哈希键，实现会话亲和性
        let hash_key = if let Some(session_id) = &context.session_id {
            format!("{}:{}", service_name, session_id)
        } else if let Some(user_id) = &context.user_id {
            format!("{}:{}", service_name, user_id)
        } else {
            service_name.to_string()
        };
        
        let instance = self.find_instance(&hash_key, &ring);
        
        Ok(instance.map(|inst| inst.clone()))
    }
}
